//#ifndef EIGEN_USE_MKL_ALL
//#define EIGEN_USE_MKL_ALL
//#endif

#include <Eigen/Dense>
#include <iostream>
#include "../data_collector/data_collector.hpp"
#include <cmath>
#include <set>
#include <ctime>

using namespace std;

void binLabel(VectorXi &Y)
{
	set<int> l;
	for (int i = 0; i < Y.size(); i++)
		l.insert(Y(i));
	for (int i = 0; i < Y.size(); i++)
	{
		if (Y(i) == *l.cbegin())
			Y(i) = 0;
		else
			Y(i) = 1;
	}
}
VectorXd LDA(MatrixXd &d)
{
	VectorXi Y = d.block(d.rows() - 1, 0, 1, d.cols()).transpose().cast<int>();
	binLabel(Y);
	int n1 = (Y.array() == 0).count(),n2=(Y.array()==1).count();
	MatrixXd X_1(d.rows()-1,n1), X_2(d.rows()-1,n2);
	int j = 0, k = 0;
	for (int i = 0; i < d.cols(); ++i)
	{
		if (Y(i) == 0)
		{
			X_1.col(j++) = d.block(0, i, d.rows() - 1, 1);
		}
		else
			X_2.col(k++) = d.block(0, i, d.rows() - 1, 1);
	}
	VectorXd m_1 = X_1.rowwise().mean();
	VectorXd m_2 = X_2.rowwise().mean();
	MatrixXd Sw = (X_1.colwise() - m_1)*((X_1.colwise() - m_1).transpose())+
		(X_2.colwise()-m_2)*((X_2.colwise()-m_2).transpose());

	VectorXd w = Sw.inverse()*(m_1 - m_2);
	w = (w.array() / w.squaredNorm()).eval();
	return w;
}

int main()
{
	DataCollector d;
	d.readDataFromFile("iris.data");
	MatrixXd X = *d.DataList();
	X = (X.block(0, 0, X.rows(), 100)).eval();
	VectorXd w=LDA(X);
	VectorXd y = w.transpose()*X.block(0, 0, X.rows() - 1, X.cols());
	cout << y.transpose() << endl;
	return 0;
}